﻿using System.Reflection;

using anydata.Interfaces;
using anydata.Services;

namespace anydata.Extensions
{
    public static class ServiceCollectionExtensions
    {
        public static IServiceCollection AddLocalServices(this IServiceCollection services)
        {
            foreach (var loopType in Assembly.GetExecutingAssembly().GetTypes())
            {
                if (!loopType.IsAbstract)
                {
                    var interfaces = loopType.GetInterfaces();
                    if (interfaces.Contains(typeof(ISingleton)))
                    {
                        services.AddSingleton(loopType);
                        continue;
                    }
                    if (interfaces.Contains(typeof(IScoped)))
                    {
                        services.AddScoped(loopType);
                        continue;
                    }
                    if (interfaces.Contains(typeof(ITransient)))
                    {
                        services.AddTransient(loopType);
                        continue;
                    }
                }
            }
            return services;
        }

        public static IEndpointConventionBuilder MapProxy(this IEndpointRouteBuilder endpoint, PathString pathMatch)
        {
            return endpoint.Map(pathMatch, async context =>
            {
                await context.Proxy(endpoint.CreateApplicationBuilder().ApplicationServices);
            });
        }

        public static IApplicationBuilder UseStatusCodeHandler(this IApplicationBuilder app, PathString codePath)
        {
            app.UseStatusCodePages(async context =>
            {
                var request = context.HttpContext.Request;
                var response = context.HttpContext.Response;
                var queryString = request.QueryString.Value;
                request.QueryString = QueryString.Create(new Dictionary<string, string?>()
                {
                    {"Method", request.Method },
                    {"Scheme", request.Scheme },
                    {"QueryString", queryString },
                    {"Host", request.Host.Value },
                    {"RequestPath", request.Path },
                    {"Protocol", request.Protocol },
                    {"StatusCode", response.StatusCode.ToString() },
                });
                response.StatusCode = 200;
                request.Path = codePath;
                await context.Next(context.HttpContext);
            });
            return app;
        }

        public static IServiceCollection AddHookServices(this IServiceCollection services)
        {
            services.AddTransient<IPostReplace, ThingLockService>();
            services.AddTransient<IPostSetFields, ThingLockService>();
            services.AddTransient<IPostInsert, ReceptionExecutorHook>();
            services.AddTransient<IPostReplace, ReceptionExecutorHook>();
            services.AddTransient<IPostSetFields, ReceptionExecutorHook>();
            services.AddTransient<IPostInsert, AssignTaskService>();
            services.AddTransient<IPostReplace, AssignTaskService>();
            services.AddTransient<IPostSetFields, AssignTaskService>();
            return services;
        }
    }
}
